yannstatic/static/2019/12/25/Archlinux-Installation.html

2528 lines
221 KiB
HTML
Raw Normal View History

2024-10-31 20:18:37 +01:00
<!DOCTYPE html><html lang="fr">
<head><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"><title>Archlinux-Installation - YannStatic</title>
<meta name="description" content="2017-06-19-Archlinux-InstallationPetit guide dinstallation dArchlinux avec Gnome 3.24.x / Plasma 5.10.x / Xfce / Mate-Desktop==============================...">
<link rel="canonical" href="https://static.rnmkcy.eu/2019/12/25/Archlinux-Installation.html"><link rel="alternate" type="application/rss+xml" title="YannStatic" href="/feed.xml">
<!-- - include head/favicon.html - -->
<link rel="shortcut icon" type="image/png" href="/assets/favicon/favicon.png"><link rel="stylesheet" href="/assets/css/main.css"><link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" ><!-- start custom head snippets --><link rel="stylesheet" href="/assets/css/expand.css">
<!-- end custom head snippets --><script>(function() {
window.isArray = function(val) {
return Object.prototype.toString.call(val) === '[object Array]';
};
window.isString = function(val) {
return typeof val === 'string';
};
window.hasEvent = function(event) {
return 'on'.concat(event) in window.document;
};
window.isOverallScroller = function(node) {
return node === document.documentElement || node === document.body || node === window;
};
window.isFormElement = function(node) {
var tagName = node.tagName;
return tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA';
};
window.pageLoad = (function () {
var loaded = false, cbs = [];
window.addEventListener('load', function () {
var i;
loaded = true;
if (cbs.length > 0) {
for (i = 0; i < cbs.length; i++) {
cbs[i]();
}
}
});
return {
then: function(cb) {
cb && (loaded ? cb() : (cbs.push(cb)));
}
};
})();
})();
(function() {
window.throttle = function(func, wait) {
var args, result, thisArg, timeoutId, lastCalled = 0;
function trailingCall() {
lastCalled = new Date;
timeoutId = null;
result = func.apply(thisArg, args);
}
return function() {
var now = new Date,
remaining = wait - (now - lastCalled);
args = arguments;
thisArg = this;
if (remaining <= 0) {
clearTimeout(timeoutId);
timeoutId = null;
lastCalled = now;
result = func.apply(thisArg, args);
} else if (!timeoutId) {
timeoutId = setTimeout(trailingCall, remaining);
}
return result;
};
};
})();
(function() {
var Set = (function() {
var add = function(item) {
var i, data = this._data;
for (i = 0; i < data.length; i++) {
if (data[i] === item) {
return;
}
}
this.size ++;
data.push(item);
return data;
};
var Set = function(data) {
this.size = 0;
this._data = [];
var i;
if (data.length > 0) {
for (i = 0; i < data.length; i++) {
add.call(this, data[i]);
}
}
};
Set.prototype.add = add;
Set.prototype.get = function(index) { return this._data[index]; };
Set.prototype.has = function(item) {
var i, data = this._data;
for (i = 0; i < data.length; i++) {
if (this.get(i) === item) {
return true;
}
}
return false;
};
Set.prototype.is = function(map) {
if (map._data.length !== this._data.length) { return false; }
var i, j, flag, tData = this._data, mData = map._data;
for (i = 0; i < tData.length; i++) {
for (flag = false, j = 0; j < mData.length; j++) {
if (tData[i] === mData[j]) {
flag = true;
break;
}
}
if (!flag) { return false; }
}
return true;
};
Set.prototype.values = function() {
return this._data;
};
return Set;
})();
window.Lazyload = (function(doc) {
var queue = {js: [], css: []}, sources = {js: {}, css: {}}, context = this;
var createNode = function(name, attrs) {
var node = doc.createElement(name), attr;
for (attr in attrs) {
if (attrs.hasOwnProperty(attr)) {
node.setAttribute(attr, attrs[attr]);
}
}
return node;
};
var end = function(type, url) {
var s, q, qi, cbs, i, j, cur, val, flag;
if (type === 'js' || type ==='css') {
s = sources[type], q = queue[type];
s[url] = true;
for (i = 0; i < q.length; i++) {
cur = q[i];
if (cur.urls.has(url)) {
qi = cur, val = qi.urls.values();
qi && (cbs = qi.callbacks);
for (flag = true, j = 0; j < val.length; j++) {
cur = val[j];
if (!s[cur]) {
flag = false;
}
}
if (flag && cbs && cbs.length > 0) {
for (j = 0; j < cbs.length; j++) {
cbs[j].call(context);
}
qi.load = true;
}
}
}
}
};
var load = function(type, urls, callback) {
var s, q, qi, node, i, cur,
_urls = typeof urls === 'string' ? new Set([urls]) : new Set(urls), val, url;
if (type === 'js' || type ==='css') {
s = sources[type], q = queue[type];
for (i = 0; i < q.length; i++) {
cur = q[i];
if (_urls.is(cur.urls)) {
qi = cur;
break;
}
}
val = _urls.values();
if (qi) {
callback && (qi.load || qi.callbacks.push(callback));
callback && (qi.load && callback());
} else {
q.push({
urls: _urls,
callbacks: callback ? [callback] : [],
load: false
});
for (i = 0; i < val.length; i++) {
node = null, url = val[i];
if (s[url] === undefined) {
(type === 'js' ) && (node = createNode('script', { src: url }));
(type === 'css') && (node = createNode('link', { rel: 'stylesheet', href: url }));
if (node) {
node.onload = (function(type, url) {
return function() {
end(type, url);
};
})(type, url);
(doc.head || doc.body).appendChild(node);
s[url] = false;
}
}
}
}
}
};
return {
js: function(url, callback) {
load('js', url, callback);
},
css: function(url, callback) {
load('css', url, callback);
}
};
})(this.document);
})();
</script><script>
(function() {
var TEXT_VARIABLES = {
version: '2.2.6',
sources: {
font_awesome: 'https://use.fontawesome.com/releases/v5.0.13/css/all.css',
jquery: '/assets/js/jquery.min.js',
leancloud_js_sdk: '//cdn.jsdelivr.net/npm/leancloud-storage@3.13.2/dist/av-min.js',
chart: 'https://cdn.bootcss.com/Chart.js/2.7.2/Chart.bundle.min.js',
gitalk: {
js: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.js',
css: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.css'
},
valine: 'https://unpkg.com/valine/dist/Valine.min.js'
},
site: {
toc: {
selectors: 'h1,h2,h3'
}
},
paths: {
search_js: '/assets/search.js'
}
};
window.TEXT_VARIABLES = TEXT_VARIABLES;
})();
</script>
</head>
<body>
<div class="root" data-is-touch="false">
<div class="layout--page js-page-root"><!----><div class="page__main js-page-main page__viewport hide-footer has-aside has-aside cell cell--auto">
<div class="page__main-inner"><div class="page__header d-print-none"><header class="header"><div class="main">
<div class="header__title">
<div class="header__brand"><svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="478.9473684210526" viewBox="0, 0, 400,478.9473684210526"><g id="svgg"><path id="path0" d="M308.400 56.805 C 306.970 56.966,303.280 57.385,300.200 57.738 C 290.906 58.803,278.299 59.676,269.200 59.887 L 260.600 60.085 259.400 61.171 C 258.010 62.428,256.198 63.600,255.645 63.600 C 255.070 63.600,252.887 65.897,252.598 66.806 C 252.460 67.243,252.206 67.600,252.034 67.600 C 251.397 67.600,247.206 71.509,247.202 72.107 C 247.201 72.275,246.390 73.190,245.400 74.138 C 243.961 75.517,243.598 76.137,243.592 77.231 C 243.579 79.293,241.785 83.966,240.470 85.364 C 239.176 86.740,238.522 88.365,237.991 91.521 C 237.631 93.665,236.114 97.200,235.554 97.200 C 234.938 97.200,232.737 102.354,232.450 104.472 C 232.158 106.625,230.879 109.226,229.535 110.400 C 228.933 110.926,228.171 113.162,226.434 119.500 C 226.178 120.435,225.795 121.200,225.584 121.200 C 225.373 121.200,225.200 121.476,225.200 121.813 C 225.200 122.149,224.885 122.541,224.500 122.683 C 223.606 123.013,223.214 123.593,223.204 124.600 C 223.183 126.555,220.763 132.911,219.410 134.562 C 218.443 135.742,217.876 136.956,217.599 138.440 C 217.041 141.424,215.177 146.434,214.532 146.681 C 214.240 146.794,214.000 147.055,214.000 147.261 C 214.000 147.467,213.550 148.086,213.000 148.636 C 212.450 149.186,212.000 149.893,212.000 150.208 C 212.000 151.386,208.441 154.450,207.597 153.998 C 206.319 153.315,204.913 150.379,204.633 147.811 C 204.365 145.357,202.848 142.147,201.759 141.729 C 200.967 141.425,199.200 137.451,199.200 135.974 C 199.200 134.629,198.435 133.224,196.660 131.311 C 195.363 129.913,194.572 128.123,193.870 125.000 C 193.623 123.900,193.236 122.793,193.010 122.540 C 190.863 120.133,190.147 118.880,188.978 115.481 C 188.100 112.928,187.151 111.003,186.254 109.955 C 185.358 108.908,184.518 107.204,183.847 105.073 C 183.280 103.273,182.497 101.329,182.108 100.753 C 181.719 100.177,180.904 98.997,180.298 98.131 C 179.693 97.265,178.939 95.576,178.624 94.378 C 178.041 92.159,177.125 90.326,175.023 87.168 C 174.375 86.196,173.619 84.539,173.342 83.486 C 172.800 81.429,171.529 79.567,170.131 78.785 C 169.654 78.517,168.697 77.511,168.006 76.549 C 167.316 75.587,166.594 74.800,166.402 74.800 C 166.210 74.800,164.869 73.633,163.421 72.206 C 160.103 68.936,161.107 69.109,146.550 69.301 C 133.437 69.474,128.581 70.162,126.618 72.124 C 126.248 72.495,125.462 72.904,124.872 73.033 C 124.282 73.163,123.088 73.536,122.219 73.863 C 121.349 74.191,119.028 74.638,117.061 74.858 C 113.514 75.254,109.970 76.350,108.782 77.419 C 107.652 78.436,100.146 80.400,97.388 80.400 C 95.775 80.400,93.167 81.360,91.200 82.679 C 90.430 83.195,89.113 83.804,88.274 84.031 C 85.875 84.681,78.799 90.910,74.400 96.243 L 73.400 97.456 73.455 106.028 C 73.526 117.055,74.527 121.238,77.820 124.263 C 78.919 125.273,80.400 127.902,80.400 128.842 C 80.400 129.202,81.075 130.256,81.900 131.186 C 83.563 133.059,85.497 136.346,86.039 138.216 C 86.233 138.886,87.203 140.207,88.196 141.153 C 89.188 142.098,90.000 143.104,90.000 143.388 C 90.000 144.337,92.129 148.594,92.869 149.123 C 93.271 149.410,93.600 149.831,93.600 150.059 C 93.600 150.286,93.932 150.771,94.337 151.136 C 94.743 151.501,95.598 153.004,96.237 154.475 C 96.877 155.947,97.760 157.351,98.200 157.596 C 98.640 157.841,99.900 159.943,101.000 162.267 C 102.207 164.817,103.327 166.644,103.825 166.876 C 104.278 167.087,105.065 168.101,105.573 169.130 C 107.658 173.348,108.097 174.093,110.006 176.647 C 111.103 178.114,112.000 179.725,112.000 180.227 C 112.000 181.048,113.425 183.163,114.678 184.200 C 115.295 184.711,117.396 188.733,117.720 190.022 C 117.855 190.562,118.603 191.633,119.381 192.402 C 120.160 193.171,121.496 195.258,122.351 197.039 C 123.206 198.820,124.167 200.378,124.487 200.501 C 124.807 200.624,125.953 202.496,127.034 204.662 C 128.114 206.828,129.676 209.299,130.505 210.153 C 131.333 211.007,132.124 212.177,132.262 212.753 C 132.618 214.239,134.291 217.048,136.288 219.5
" href="/">YannStatic</a></div><!--<button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button>--><!-- <li><button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button></li> -->
<!-- Champ de recherche -->
<div id="searchbox" class="search search--dark" style="visibility: visible">
<div class="main">
<div class="search__header"></div>
<div class="search-bar">
<div class="search-box js-search-box">
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
<input id="search-input" type="text" />
<!-- <div class="search-box__icon-clear js-icon-clear">
<a><i class="fas fa-times"></i></a>
</div> -->
</div>
</div>
</div>
</div>
<!-- Script pointing to search-script.js -->
<script>/*!
* Simple-Jekyll-Search
* Copyright 2015-2020, Christian Fei
* Licensed under the MIT License.
*/
(function(){
'use strict'
var _$Templater_7 = {
compile: compile,
setOptions: setOptions
}
const options = {}
options.pattern = /\{(.*?)\}/g
options.template = ''
options.middleware = function () {}
function setOptions (_options) {
options.pattern = _options.pattern || options.pattern
options.template = _options.template || options.template
if (typeof _options.middleware === 'function') {
options.middleware = _options.middleware
}
}
function compile (data) {
return options.template.replace(options.pattern, function (match, prop) {
const value = options.middleware(prop, data[prop], options.template)
if (typeof value !== 'undefined') {
return value
}
return data[prop] || match
})
}
'use strict';
function fuzzysearch (needle, haystack) {
var tlen = haystack.length;
var qlen = needle.length;
if (qlen > tlen) {
return false;
}
if (qlen === tlen) {
return needle === haystack;
}
outer: for (var i = 0, j = 0; i < qlen; i++) {
var nch = needle.charCodeAt(i);
while (j < tlen) {
if (haystack.charCodeAt(j++) === nch) {
continue outer;
}
}
return false;
}
return true;
}
var _$fuzzysearch_1 = fuzzysearch;
'use strict'
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
function FuzzySearchStrategy () {
this.matches = function (string, crit) {
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
}
}
'use strict'
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
function LiteralSearchStrategy () {
this.matches = function (str, crit) {
if (!str) return false
str = str.trim().toLowerCase()
crit = crit.trim().toLowerCase()
return crit.split(' ').filter(function (word) {
return str.indexOf(word) >= 0
}).length === crit.split(' ').length
}
}
'use strict'
var _$Repository_4 = {
put: put,
clear: clear,
search: search,
setOptions: __setOptions_4
}
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
function NoSort () {
return 0
}
const data = []
let opt = {}
opt.fuzzy = false
opt.limit = 10
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = NoSort
opt.exclude = []
function put (data) {
if (isObject(data)) {
return addObject(data)
}
if (isArray(data)) {
return addArray(data)
}
return undefined
}
function clear () {
data.length = 0
return data
}
function isObject (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
}
function isArray (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
}
function addObject (_data) {
data.push(_data)
return data
}
function addArray (_data) {
const added = []
clear()
for (let i = 0, len = _data.length; i < len; i++) {
if (isObject(_data[i])) {
added.push(addObject(_data[i]))
}
}
return added
}
function search (crit) {
if (!crit) {
return []
}
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
}
function __setOptions_4 (_opt) {
opt = _opt || {}
opt.fuzzy = _opt.fuzzy || false
opt.limit = _opt.limit || 10
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = _opt.sort || NoSort
opt.exclude = _opt.exclude || []
}
function findMatches (data, crit, strategy, opt) {
const matches = []
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
const match = findMatchesInObject(data[i], crit, strategy, opt)
if (match) {
matches.push(match)
}
}
return matches
}
function findMatchesInObject (obj, crit, strategy, opt) {
for (const key in obj) {
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
return obj
}
}
}
function isExcluded (term, excludedTerms) {
for (let i = 0, len = excludedTerms.length; i < len; i++) {
const excludedTerm = excludedTerms[i]
if (new RegExp(excludedTerm).test(term)) {
return true
}
}
return false
}
/* globals ActiveXObject:false */
'use strict'
var _$JSONLoader_2 = {
load: load
}
function load (location, callback) {
const xhr = getXHR()
xhr.open('GET', location, true)
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
xhr.send()
}
function createStateChangeListener (xhr, callback) {
return function () {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
callback(null, JSON.parse(xhr.responseText))
} catch (err) {
callback(err, null)
}
}
}
}
function getXHR () {
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
}
'use strict'
var _$OptionsValidator_3 = function OptionsValidator (params) {
if (!validateParams(params)) {
throw new Error('-- OptionsValidator: required options missing')
}
if (!(this instanceof OptionsValidator)) {
return new OptionsValidator(params)
}
const requiredOptions = params.required
this.getRequiredOptions = function () {
return requiredOptions
}
this.validate = function (parameters) {
const errors = []
requiredOptions.forEach(function (requiredOptionName) {
if (typeof parameters[requiredOptionName] === 'undefined') {
errors.push(requiredOptionName)
}
})
return errors
}
function validateParams (params) {
if (!params) {
return false
}
return typeof params.required !== 'undefined' && params.required instanceof Array
}
}
'use strict'
var _$utils_9 = {
merge: merge,
isJSON: isJSON
}
function merge (defaultParams, mergeParams) {
const mergedOptions = {}
for (const option in defaultParams) {
mergedOptions[option] = defaultParams[option]
if (typeof mergeParams[option] !== 'undefined') {
mergedOptions[option] = mergeParams[option]
}
}
return mergedOptions
}
function isJSON (json) {
try {
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
return true
}
return false
} catch (err) {
return false
}
}
var _$src_8 = {};
(function (window) {
'use strict'
let options = {
searchInput: null,
resultsContainer: null,
json: [],
success: Function.prototype,
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
templateMiddleware: Function.prototype,
sortMiddleware: function () {
return 0
},
noResultsText: 'No results found',
limit: 10,
fuzzy: false,
debounceTime: null,
exclude: []
}
let debounceTimerHandle
const debounce = function (func, delayMillis) {
if (delayMillis) {
clearTimeout(debounceTimerHandle)
debounceTimerHandle = setTimeout(func, delayMillis)
} else {
func.call()
}
}
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
/* removed: const _$Templater_7 = require('./Templater') */;
/* removed: const _$Repository_4 = require('./Repository') */;
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
const optionsValidator = _$OptionsValidator_3({
required: requiredOptions
})
/* removed: const _$utils_9 = require('./utils') */;
window.SimpleJekyllSearch = function (_options) {
const errors = optionsValidator.validate(_options)
if (errors.length > 0) {
throwError('You must specify the following required options: ' + requiredOptions)
}
options = _$utils_9.merge(options, _options)
_$Templater_7.setOptions({
template: options.searchResultTemplate,
middleware: options.templateMiddleware
})
_$Repository_4.setOptions({
fuzzy: options.fuzzy,
limit: options.limit,
sort: options.sortMiddleware,
exclude: options.exclude
})
if (_$utils_9.isJSON(options.json)) {
initWithJSON(options.json)
} else {
initWithURL(options.json)
}
const rv = {
search: search
}
typeof options.success === 'function' && options.success.call(rv)
return rv
}
function initWithJSON (json) {
_$Repository_4.put(json)
registerInput()
}
function initWithURL (url) {
_$JSONLoader_2.load(url, function (err, json) {
if (err) {
throwError('failed to get JSON (' + url + ')')
}
initWithJSON(json)
})
}
function emptyResultsContainer () {
options.resultsContainer.innerHTML = ''
}
function appendToResultsContainer (text) {
options.resultsContainer.innerHTML += text
}
function registerInput () {
options.searchInput.addEventListener('input', function (e) {
if (isWhitelistedKey(e.which)) {
emptyResultsContainer()
debounce(function () { search(e.target.value) }, options.debounceTime)
}
})
}
function search (query) {
if (isValidQuery(query)) {
emptyResultsContainer()
render(_$Repository_4.search(query), query)
}
}
function render (results, query) {
const len = results.length
if (len === 0) {
return appendToResultsContainer(options.noResultsText)
}
for (let i = 0; i < len; i++) {
results[i].query = query
appendToResultsContainer(_$Templater_7.compile(results[i]))
}
}
function isValidQuery (query) {
return query && query.length > 0
}
function isWhitelistedKey (key) {
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
}
function throwError (message) {
throw new Error('SimpleJekyllSearch --- ' + message)
}
})(window)
}());
</script>
<!-- Configuration -->
<script>
SimpleJekyllSearch({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
json: '/search.json',
//searchResultTemplate: '<li><a href="https://static.rnmkcy.eu{url}">{date}&nbsp;{title}</a></li>'
searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{title}</a></li>'
})
</script>
<!-- Fin déclaration champ de recherche --></div><nav class="navigation">
<ul><li class="navigation__item"><a href="/archive.html">Etiquettes</a></li><li class="navigation__item"><a href="/htmldoc.html">Documents</a></li><li class="navigation__item"><a href="/liens_ttrss.html">Liens</a></li><li class="navigation__item"><a href="/aide-jekyll-text-theme.html">Aide</a></li></ul>
</nav></div>
</header>
</div><div class="page__content"><div class ="main"><div class="grid grid--reverse">
<div class="col-main cell cell--auto"><!-- start custom main top snippet --><div id="results-container" class="search-result js-search-result"></div><!-- end custom main top snippet -->
<article itemscope itemtype="http://schema.org/Article"><div class="article__header"><header><h1 style="color:Tomato;">Archlinux-Installation</h1></header></div><meta itemprop="headline" content="Archlinux-Installation"><div class="article__info clearfix"><ul class="left-col menu"><li>
<a class="button button--secondary button--pill button--sm"
href="/archive.html?tag=archlinux">archlinux</a>
</li></ul><ul class="right-col menu"><li>
<i class="far fa-calendar-alt"></i>&nbsp;<span title="Création" style="color:#FF00FF">25&nbsp;déc.&nbsp;&nbsp;2019</span>
<span title="Modification" style="color:#00FF7F">23&nbsp;nov.&nbsp;&nbsp;2018</span></li></ul></div><meta itemprop="datePublished" content="2018-11-23T00:00:00+01:00">
<meta itemprop="keywords" content="archlinux"><div class="js-article-content">
<div class="layout--article"><!-- start custom article top snippet -->
<style>
#myBtn {
display: none;
position: fixed;
bottom: 10px;
right: 10px;
z-index: 99;
font-size: 12px;
font-weight: bold;
border: none;
outline: none;
background-color: white;
color: black;
cursor: pointer;
padding: 5px;
border-radius: 4px;
}
#myBtn:hover {
background-color: #555;
}
</style>
<button onclick="topFunction()" id="myBtn" title="Haut de page">&#8679;</button>
<script>
//Get the button
var mybutton = document.getElementById("myBtn");
// When the user scrolls down 20px from the top of the document, show the button
window.onscroll = function() {scrollFunction()};
function scrollFunction() {
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
mybutton.style.display = "block";
} else {
mybutton.style.display = "none";
}
}
// When the user clicks on the button, scroll to the top of the document
function topFunction() {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
}
</script>
<!-- end custom article top snippet -->
<div class="article__content" itemprop="articleBody"><details>
<summary><b>Afficher/cacher Sommaire</b></summary>
<!-- affichage sommaire -->
<div class="toc-aside js-toc-root"></div>
</details><h1 id="2017-06-19-archlinux-installation">2017-06-19-Archlinux-Installation</h1>
<p>Petit guide dinstallation dArchlinux avec Gnome 3.24.x / Plasma 5.10.x / Xfce / Mate-Desktop
==============================================================================================</p>
<p>Dans ce petit guide, je vais détailler linstallation dArchlinux avec Gnome 3.24 et suivant, Plasma 5.10.x, Xfce et Mate-Desktop. Linstallation terminée proposera un environnement suffisamment étoffé pour être utilisable.</p>
<p>Pour des raisons pratiques, je naborde nullement lajout de matériel comme les imprimantes, les scanners, ou encore les webcams. Je vous renvoie aux wikis anglophone <a href="https://wiki.archlinux.org/">https://wiki.archlinux.org/</a> et francophone <a href="http://wiki.archlinux.fr/Accueil">http://wiki.archlinux.fr/Accueil</a> pour ce genre de manipulations.</p>
<p><strong>NOTE 1 :</strong> Ce tutoriel est <strong>volontairement simplifié</strong>. Il va vous permettre de voir comment installer une ArchLinux <strong>en solo</strong>. <strong>Ensuite, sil y a des spécificités liées à votre matériel, cest au cas par cas quil faut regarder et compulser frénétiquement les wikis ci-dessus.</strong> Si vous voulez installer une Archlinux **en parallèle **dune installation de MS-Windows, cest en dehors du cadre de ce document.</p>
<p><strong>NOTE 2 :</strong> Pour Lxde et LXQt, il faudra voir avec le tutoriel de février 2016 : <a href="http://frederic.bezies.free.fr/blog/?p=14045">http://frederic.bezies.free.fr/blog/?p=14045</a></p>
<p><strong>NOTE 3 :</strong> Pour Budgie Desktop et Cinnamon, je vous conseille de vous reporter au tutoriel davril 2017 : <a href="http://frederic.bezies.free.fr/blog/?p=15985">http://frederic.bezies.free.fr/blog/?p=15985</a></p>
<p><strong>NOTE 4 :</strong> Les images ISO dinstallation ne sont plus quen 64 bits à compter du 1er mars 2017. Si vous avez un vieux PC en 32 bits, il vous faudra la dernière image ISO disponible sur le site <a href="https://www.archlinux32.org/">Archlinux32</a>.</p>
<p>Pour cette version du guide, je me suis basé sur la dernière ISO officielle, celle qui utilise les scripts dinstallation. En juin 2017, cest la 2017.06.01.</p>
<p>Merci à Ewolnux, Xarkam, Frédéric Sierra, Ludovic Riand, Vincent Manillier, Thomas Pawlowski, Quentin Bihet, Igor Milhit et André Ray pour leurs conseils et remarques. Ce document est proposé sous licence <a href="http://creativecommons.org/licenses/by-sa/4.0">CC-BY-SA 4.0.</a></p>
<h2 id="i-installons-notre-base">I) Installons notre base</h2>
<p>Installer une Archlinux, cest comme construire une maison. On commence par les fondations, et on rajoute les murs et le reste par la suite. Limage ISO utilisée est la archlinux-2017.06.01-x86_64.iso, mise en ligne début juin 2017.</p>
<p>La machine virtuelle est une machine VirtualBox à laquelle jai rajouté un disque virtuel de 128 Go. Des points spécifiques concernant lutilisation dans VirtualBox sont indiqués. Par défaut, le noyau proposé par Archlinux est un noyau « court terme ». Si vous voulez un noyau LTS, je vous expliquerai comment faire.</p>
<p>Dans cette partie, certaines sections seront dédoublées à cause des différences entre linstallation en mode Bios et en mode UEFI.</p>
<p>Commençons par une installation en mode Bios, du point de vue du partitionnement et de lattribution des partitions. Si vous utilisez une machine réelle ou virtuelle avec lUEFI, des instructions spécifiques sont détaillées par la suite.</p>
<h4 id="partitionnement-et-attribution-des-partitions-en-mode-bios-">Partitionnement et attribution des partitions en mode Bios :</h4>
<p>Voici donc lécran qui nous permet de démarrer. Comme vous pouvez le voir, on peut démarrer soit avec un noyau 32 soit avec un noyau 64 bits. Il ny a plus grande différence, sauf au niveau de certains logiciels typiquement 32 bits, mais jexpliquerai plus bas comment faire cohabiter 32 et 64 bits.</p>
<p><img src="file://pictures/001.png" alt="Illustration 1: écran de démarrage en mode Bios, uniquement en 64 bits (depuis mars 2017)" /></p>
<p><em>Illustration 1: écran de démarrage en mode Bios, uniquement en 64 bits (depuis mars 2017)</em></p>
<p>La première chose à faire, cest davoir le clavier français :</p>
<p><code class="language-plaintext highlighter-rouge">loadkeys fr</code></p>
<p>Pour le partitionnement, si vous avez peur de faire des bêtises, il est plus prudent de passer par un LiveCD comme gParted disponible à ladresse suivante : <a href="http://gparted.org/">http://gparted.org/</a></p>
<p>Avec cfdisk, sur lécran de démarrage suivant, on choisit loption « dos » pour le « label type » à appliquer.</p>
<p><img src="file://pictures/002.png" alt="Illustration 2: premier démarrage de cfdisk" /></p>
<p><em>Illustration 2: premier démarrage de cfdisk</em></p>
<p>Pour le partitionnement en question :</p>
<table>
<thead>
<tr>
<th>Référence</th>
<th>Point de montage</th>
<th>Taille</th>
<th>Système de fichiers</th>
</tr>
</thead>
<tbody>
<tr>
<td>/dev/sda1</td>
<td>/boot</td>
<td>512 Mo</td>
<td>ext2</td>
</tr>
<tr>
<td>/dev/sda2</td>
<td> </td>
<td>Taille de la mémoire vive ou plus</td>
<td>swap</td>
</tr>
<tr>
<td>/dev/sda3</td>
<td>/</td>
<td>20 Go</td>
<td>ext4</td>
</tr>
<tr>
<td>/dev/sda4</td>
<td>/home</td>
<td>Le reste du disque</td>
<td>ext4</td>
</tr>
</tbody>
</table>
<p>Il ne faut pas oublier de définir la partition attribuée à /boot comme démarrable (bootable). Ce qui donne lécran suivant dans cfdisk.</p>
<p><img src="file://pictures/003.png" alt="Illustration 3: cfdisk en action" /></p>
<p><em>Illustration 3: cfdisk en action</em></p>
<p>Pour le formatage des partitions, il suffit dentrer les commandes suivantes :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkfs.ext2 /dev/sda1
mkfs.ext4 /dev/sda3
mkfs.ext4 /dev/sda4
</code></pre></div></div>
<p>Sans oublier la partition de swap :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkswap /dev/sda2
swapon /dev/sda2
</code></pre></div></div>
<p>On va ensuite créer les points de montage et y associer les partitions qui correspondent.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mount /dev/sda3 /mnt
mkdir /mnt/{boot,home}
mount /dev/sda1 /mnt/boot
mount /dev/sda4 /mnt/home
</code></pre></div></div>
<p>On peut passer ensuite à linstallation de la base.</p>
<h4 id="partitionnement-et-attribution-des-partitions-en-mode-uefi-">Partitionnement et attribution des partitions en mode UEFI :</h4>
<p>Voici donc lécran qui nous permet de démarrer en mode UEFI, supporté uniquement pour la version 64 bits.</p>
<p><img src="file://pictures/004.png" alt="Illustration 4: démarrage en mode UEFI" />
<em>Illustration 4: démarrage en mode UEFI</em></p>
<p>Comme pour la section concernant le partitionnement en mode Bios, si vous craignez de faire des bêtises, vous pouvez utiliser gParted en mode liveCD : <a href="http://gparted.org/">http://gparted.org/</a></p>
<p>Il faut se souvenir quil faut <strong>obligatoirement</strong> une table de partition GPT en cas dinstallation en mode UEFI. Si vous nêtes pas passé par gParted, il faut utiliser loutil cgdisk.</p>
<table>
<thead>
<tr>
<th>Référence</th>
<th>Point de montage</th>
<th>Taille</th>
<th>Système de fichiers</th>
</tr>
</thead>
<tbody>
<tr>
<td>/dev/sda1</td>
<td>/</td>
<td>20 Go</td>
<td>ext4</td>
</tr>
<tr>
<td>/dev/sda2</td>
<td>/boot</td>
<td>512 Mo</td>
<td>fat32</td>
</tr>
<tr>
<td>/dev/sda3</td>
<td> </td>
<td>Taille de la mémoire vive ou plus</td>
<td>swap</td>
</tr>
<tr>
<td>/dev/sda4</td>
<td>/home</td>
<td>Le reste du disque</td>
<td>ext4</td>
</tr>
</tbody>
</table>
<p><strong>Note :</strong> pour la partition /boot, il faut quelle soit étiquetée en EF00 à sa création. Pour le swap, cest la référence 8200.</p>
<p><img src="file://pictures/005.png" alt="Illustration 5: cgdisk en action pour un partitionnement avec un UEFI" />
<em>Illustration 5: cgdisk en action pour un partitionnement avec un UEFI</em></p>
<p>Le partitionnement à appliquer ? Cest le suivant :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkfs.ext4 /dev/sda1
mkfs.fat -F32 /dev/sda2
mkfs.ext4 /dev/sda4
</code></pre></div></div>
<p>Sans oublier la partition de swap :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkswap /dev/sda3
swapon /dev/sda3
</code></pre></div></div>
<p>Et pour les points de montage :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mount /dev/sda1 /mnt
mkdir /mnt/{boot,home}
mount /dev/sda2 /mnt/boot
mount /dev/sda4 /mnt/home
</code></pre></div></div>
<p>On peut passer à linstallation de la base.</p>
<h4 id="installation-de-la-base-de-notre-archlinux-">Installation de la base de notre Archlinux :</h4>
<p>Après avoir procédé au partitionnement et à lattribution des partitions, on peut attaquer les choses sérieuses, à savoir récupérer la base de notre installation. mais avant toute chose, choisissons le miroir le plus rapide.</p>
<p><strong>Note :</strong> si vous utilisez une connexion wifi, je vous conseille de voir cette page du wiki anglophone darchlinux : <a href="https://wiki.archlinux.org/index.php/Netctl">https://wiki.archlinux.org/index.php/Netctl</a></p>
<p>Avec loutil nano nous allons modifier le fichier /etc/pacman.d/mirrorlist pour ne garder quun seul miroir. Le plus proche géographiquement et aussi le plus rapide possible. Pour une personne vivant en France, cest <strong>de préférence</strong> mir.archlinux.fr et / ou archlinux.polymorf.fr.</p>
<p><img src="file://pictures/006.png" alt="Illustration 6: la liste des miroirs disponibles." /></p>
<p><em>Illustration 6: la liste des miroirs disponibles.</em></p>
<p>Jai utilisé le raccourci clavier suivant : <strong>ALT+R</strong>. On entre dans un premier temps « Server » (sans les guillemets). On presse la touche entrée. On saisit « #Server » (sans les guillemets) pour commenter tous les serveurs.</p>
<p>Avec le raccourci clavier <strong>CTRL+W</strong>, il suffit de saisir le nom du serveur quon veut utiliser et enlever la « # » sur sa ligne. Un <strong>CTRL+X</strong> suivi de la touche « y » (pour yes) permet denregistrer la modification.</p>
<p>On passe à linstallation de la base. La deuxième ligne rajoute certains outils bien pratique à avoir dès le départ. On peut ensuite sattaquer à linstallation proprement dite.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacstrap /mnt base base-devel
pacstrap /mnt zip unzip p7zip vim mc alsa-utils syslog-ng mtools dosfstools lsb-release ntfs-3g exfat-utils **(sur une seule ligne !)**
</code></pre></div></div>
<p>Si on veut utiliser un noyau linux long terme, il faut rajouter à la deuxième ligne pacstrap le paquet linux-lts. Pour ntfs-3g, cest utile si vous êtes amené à utiliser des disques formatés en ntfs. Si ce nest pas le cas, vous pouvez lignorer allègrement.</p>
<p><strong>Note :</strong> exfat-utils ma été conseillé par André Ray pour la prise en charge des cartes SD de grande capacité. Merci pour le retour !</p>
<p>Maintenant que les outils de base sont installés, il faut générer le fichier /etc/fstab qui liste les partitions présentes.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>genfstab -U -p /mnt &gt;&gt; /mnt/etc/fstab
</code></pre></div></div>
<p>Au tour du chargeur de démarrage. Jutilise Grub2 qui soccupe de tout et récupère les paquets qui vont bien. Le paquet os-prober est indispensable pour un double démarrage.</p>
<p>1) Pour un ordinateur avec BIOS :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacstrap /mnt grub os-prober
</code></pre></div></div>
<p>2) Pour un ordinateur avec UEFI :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacstrap /mnt grub os-prober efibootmgr
</code></pre></div></div>
<p>On passe aux réglages de lOS quon vient dinstaller. Il faut donc y entrer. On utilise la commande suivante :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>arch-chroot /mnt
</code></pre></div></div>
<p>Avant daller plus loin, voici quelques infos pratiques. Cela concerne les pays francophones comme la Belgique, la Suisse, le Luxembourg ou encore le Canada francophone.</p>
<p>Nous allons par la suite créer des fichiers qui demanderont des valeurs précises. Les voici résumées ici :</p>
<table>
<thead>
<tr>
<th>Pays</th>
<th>Locale (LANG)</th>
<th>Clavier (KEYMAP)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Belgique</td>
<td>fr_BE.UTF-8</td>
<td>be-latin1</td>
</tr>
<tr>
<td>Canada</td>
<td>fr_CA.UTF-8</td>
<td>cf</td>
</tr>
<tr>
<td>France</td>
<td>fr_FR.UTF-8</td>
<td>fr-latin9</td>
</tr>
<tr>
<td>Luxembourg</td>
<td>fr_LU.UTF-8</td>
<td>fr-latin9</td>
</tr>
<tr>
<td>Suisse</td>
<td>fr_CH.UTF-8</td>
<td>fr_CH</td>
</tr>
</tbody>
</table>
<p>Pour avoir le bon clavier en mode texte, créez le fichier /etc/vconsole.conf. Il suffira de ladapter si le besoin sen fait sentir.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>KEYMAP=fr-latin9
FONT=lat9w-16
</code></pre></div></div>
<p>Pour avoir la localisation française, le fichier /etc/locale.conf doit contenir la bonne valeur pour LANG. Pour un personne en France métropolitaine :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>LANG=fr_FR.UTF-8
LC_COLLATE=C
</code></pre></div></div>
<p><strong>Note :</strong> La deuxième ligne est nécessaire si on apprécie davoir le tri par la « casse » (majuscule puis minuscule) activé. Merci à Igor Milhit pour la remarque !</p>
<p>Il faut vérifier que la ligne fr_FR.UTF-8 UTF-8 dans le fichier /etc/locale.gen na pas de # devant elle. Ainsi que la ligne en_US.UTF-8 UTF-8. Évidemment, la valeur fr_FR.UTF-8 doit être modifiée si besoin est. On va maintenant générer les traductions :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>locale-gen
</code></pre></div></div>
<p>On peut spécifier la locale pour la session courante, à modifier en fonction de votre pays :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>export LANG=fr_FR.UTF-8
</code></pre></div></div>
<p>Le nom de la machine ? Il est contenu dans le fichier <strong>/etc/hostname</strong>. Il suffit de taper le nom sur la première ligne. Par exemple : <em>fredo-archlinux-gnome.</em> À remplacer par le nom de la machine bien entendu.</p>
<p>Le fuseau horaire ? Une seule étape. Prenons le cas dune installation avec le fuseau horaire de Paris. Tout dépend de votre lieu de résidence. On commence par créer un lien symbolique :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime
</code></pre></div></div>
<p>Ensuite, deux cas se présentent. Soit on a une machine en mono-démarrage sur Archlinux, et on peut demander à ce que lheure appliquée soit UTC, soit un double démarrage avec MS-Windows. Restons dans ce premier cas.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hwclock --systohc --utc
</code></pre></div></div>
<p><strong>Sinon, on ne touche à rien.</strong> MS-Windows est un goujat dans ce dojuinne.</p>
<p>Étape suivante ? Générer le fichier de configuration de Grub.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkinitcpio -p linux ou **linux-lts** si vous voulez le noyau lts.
grub-mkconfig -o /boot/grub/grub.cfg
</code></pre></div></div>
<p><strong>Note</strong> : si vous avez une « hurlante » contenant « /run/lvm/lvmetad.socket: connect failed » ou quelque chose dapprochant, ce nest pas un bug. Cest une alerte sans conséquence. Cf <a href="https://wiki.archlinux.org/index.php/GRUB#Boot_freezes">https://wiki.archlinux.org/index.php/GRUB#Boot_freezes</a></p>
<p>1) Pour une installation en mode BIOS :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>grub-install --no-floppy --recheck /dev/sda
</code></pre></div></div>
<p><strong>2) Pour une installation en mode UEFI :</strong></p>
<p>Il faut déjà vérifier la présence de la variable efivars. Si en entrant la commande mount, vous avez dans la liste une réponse du style :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>efivars on /sys/firmware/efi/efivars type efivars (rw,nosuid,nodev,noexec,relatime)
</code></pre></div></div>
<p>Dans ce cas, vous pouvez aller directement à la ligne du grub-install, ci-dessous, et sauter la première ligne de commande. La deuxième ligne est dun seul tenant.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mount -t efivarfs efivarfs /sys/firmware/efi/efivarfs
grub-install --target=x86\_64-efi --efi-directory=/boot --bootloader-id=arch\_grub --recheck
</code></pre></div></div>
<p>De plus, pour éviter tout problème de démarrage par la suite, il est conseillé de rajouter les commandes suivantes :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir /boot/EFI/boot
cp /boot/EFI/arch\_grub/grubx64.efi /boot/EFI/boot/bootx64.efi
</code></pre></div></div>
<p><img src="file://pictures/007.png" alt="Illustration 7 : Génération du noyau linux 4.11.3 début juin 2017" /></p>
<p><em>Illustration 7 : Génération du noyau linux 4.11.3 début juin 2017</em></p>
<p>Bien entendu, aucune erreur ne doit apparaître. On donne un mot de passe au compte root :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>passwd root
</code></pre></div></div>
<p>Pour le réseau, installer et activer NetworkManager est une bonne idée. Vous pouvez remplacer NetworkManager par le duo wicd et wicd-gtk <strong>en cas de problème.</strong> Pour wicd :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman -Syy wicd wicd-gtk
systemctl enable wicd
</code></pre></div></div>
<p>Et pour Networkmanager :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman -Syy networkmanager
systemctl enable NetworkManager
</code></pre></div></div>
<p><strong>NOTE 1 :</strong> si vous nutilisez pas NetworkManager, je vous renvoie à cette page du wiki anglophone dArchlinux, qui vous aidera dans cette tâche : <a href="https://wiki.archlinux.org/index.php/Netctl">https://wiki.archlinux.org/index.php/Netctl</a></p>
<p><strong>NOTE 2 :</strong> netctl et networkmanager rentrent en conflit et <strong>ne doivent pas</strong> être utilisé en même temps. Dailleurs, netctl et wicd entre aussi en conflit. Une règle simple : un seul gestionnaire de connexion réseau à la fois !</p>
<p><strong>NOTE 3 :</strong> si vous voulez utiliser des réseaux wifi directement avec NetworkManager et son applet, le paquet gnome-keyring est indispensable. Merci à Vincent Manillier pour linfo.</p>
<p>Dernier réglage, <strong>optionnel</strong> si on veut avoir accès à loutil yaourt, il faut ajouter ceci au fichier /etc/pacman.conf à la fin. Une fois yaourt installé, on peut enlever <strong>sans aucun risque</strong> les lignes en question.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[archlinuxfr]
SigLevel = Never
Server = http://repo.archlinux.fr/\$arch
</code></pre></div></div>
<p>Si vous voulez utiliser un outil comme Skype (qui est uniquement en 32 bits) et que vous installez un système 64 bits, il faut décommenter (enlever les #) des lignes suivantes :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#[multilib]
#Include = /etc/pacman.d/mirrorlist
</code></pre></div></div>
<p>On peut maintenant quitter tout, démonter proprement les partitions et redémarrer.</p>
<p>Cest un peu plus délicat quauparavant. Au moins, on voit les étapes à suivre.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>exit
umount -R /mnt
reboot
</code></pre></div></div>
<p>Voilà, on peut redémarrer. On va passer à la suite, largement moins ennuyeuse !</p>
<h2 id="ii-installons-maintenant-lenvironnement-graphique-">II) Installons maintenant lenvironnement graphique !</h2>
<p>Nous attaquons donc la partie la plus intéressante, linstallation de lenvironnement graphique. Il y a des étapes communes à tous les environnements. Un peu plus loin est indiquée la partie concernant <strong>uniquement</strong> Gnome.</p>
<p>Une fois le système démarré, on se connecte <strong>en root</strong>. Étant donné que jai installé NetworkManager (ou wicd selon les goûts) à létape précédente, le réseau fonctionne directement. On tape les lignes de commande suivantes pour mettre à jour les dépôts et installer yaourt un outil qui va nous simplifier grandement la vie.</p>
<p>Ainsi que ntp (synchronisation de lheure en réseau) et cronie (pour les tâches dadministration à automatiser). Linstallation de yaourt dépend de lajout du dépôt archlinuxfr, bien entendu.</p>
<p>Une fois yaourt installé (si on le désire), on peut enlever le dépôt archlinux du fichier /etc/pacman.conf car yaourt est disponible sur AUR.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman -Syy
pacman -S yaourt ntp cronie
</code></pre></div></div>
<p><strong>Note :</strong> si on veut avoir les logs en clair en cas de problème, il faut modifier avec nano (ou vim) le fichier /etc/systemd/journald.conf en remplaçant la ligne :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#ForwardToSyslog=no
</code></pre></div></div>
<p>par :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ForwardToSyslog=yes
</code></pre></div></div>
<p>Les outils en place, on lance alsamixer avec la commande du même nom, pour configurer le niveau sonore :</p>
<p><img src="008.png" alt="Illustration 8: alsamixer en action" /></p>
<p><em>Illustration 8: alsamixer en action</em></p>
<p>Une fois lensemble configuré, pour le conserver tel quel, il suffit dentrer :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>alsactl store
</code></pre></div></div>
<p>Nous sommes dans le multimédia ? Restons-y.</p>
<p>On va installer lensemble des greffons gstreamer qui nous donneront accès aux fichiers multimédias une fois Gnome lancé. Si vous navez pas installé yaourt, il faudra le remplacer par <strong>pacman -S</strong> ou <strong>sudo pacman -S</strong> quand vous utiliserez votre compte utilisateur « normal » plus tard.</p>
<p>Pour lexécution de la ligne suivante, il est demandé de choisir un support pour OpenGL. Pour le moment, on choisit MesaGL. La modification correspondant à votre matériel sera faite lors de linstallation de Xorg. Ainsi que la version « libx264 » proposé en premier choix. Merci à Adrien de Linuxtricks pour mavoir aidé à réduire la longueur de la ligne de commande :)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman -S gst-plugins-{base,good,bad,ugly} gst-libav
</code></pre></div></div>
<p>gst-libav ? Il prend en charge tout ce qui est x264 et apparenté.</p>
<p>Passons à linstallation de Xorg. Le paquet xf86-input-evdev est obsolète depuis début janvier 2017, à cause du passage à xorg-server 1.19.</p>
<p><strong>Note :</strong> il ny a pas despace entre le et le { vers la fin de la commande suivante.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman -S xorg-{server,xinit,apps} xf86-input-{mouse,keyboard} xdg-user-dirs
</code></pre></div></div>
<p>Si on utilise un ordinateur portable avec un pavé tactile, il faut rajouter le paquet xf86-input-synaptics ou <strong>de préférence</strong> xf86-input-libinput.</p>
<p>Il faut ensuite choisir le pilote pour le circuit vidéo. Voici les principaux pilotes, sachant que le paquet xf86-video-vesa englobe une énorme partie des circuits graphiques, dont ceux non listés dans le tableau un peu plus loin. En cas de doute : <a href="https://wiki.archlinux.org/index.php/Xorg#Driver_installation">https://wiki.archlinux.org/index.php/Xorg#Driver_installation</a></p>
<p>Pour Nvidia, cest un casse-tête au niveau des pilotes propriétaires. Le plus simple est de se référer au wiki dArchlinux : <a href="https://wiki.archlinux.org/index.php/NVIDIA">https://wiki.archlinux.org/index.php/NVIDIA</a></p>
<table>
<thead>
<tr>
<th>Circuits graphiques</th>
<th>Pilotes libres</th>
<th>Pilotes non libres (si existant)</th>
</tr>
</thead>
<tbody>
<tr>
<td>AMD</td>
<td>xf86-video-ati</td>
<td>Catalyst (disponible sur AUR, le dépôt utilisateur)</td>
</tr>
<tr>
<td>Intel</td>
<td>xf86-video-intel</td>
<td> </td>
</tr>
<tr>
<td>Nvidia</td>
<td>xf86-video-nouveau</td>
<td>Nvidia (cf le wiki darchlinux) pour la version à installer en fonction de la carte graphique</td>
</tr>
</tbody>
</table>
<p>Dans le cas dune machine virtuelle, jai utilisé le paquet <strong>xf86-video-vesa</strong>. On passe ensuite à linstallation des polices. Voici la ligne de commande pour les principales.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman -S ttf-{bitstream-vera,liberation,freefont,dejavu}
</code></pre></div></div>
<p><strong>Note 2 :</strong> pour les polices Microsoft, le paquet ttf-ms-fonts, elles sont sur le dépôt AUR, donc il faut utiliser yaourt pour les récupérer et les installer.</p>
<p>Cependant, depuis larrivée de Pacman 4.2, il est impossible de construire un paquet avec loption asroot. Donc vous devrez lancer la commande ci-dessous en tant quutilisateur simple.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yaourt -S ttf-ms-fonts
</code></pre></div></div>
<p>Si vous faites une installation dans VirtualBox, il faut deux paquets. En plus de xf86-video-vesa, il faut le paquet virtualbox-guest-utils. Cependant, il y a deux choix qui arrive pour ce paquet.</p>
<p>Ce qui donne :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman -S xf86-video-vesa
pacman -S virtualbox-guest-utils
</code></pre></div></div>
<p><img src="file://pictures/009.png" alt="Illustration 9: Choix du paquet à installer concernant virtualbox-guest-utils" /></p>
<p><em>Illustration 9: Choix du paquet à installer concernant virtualbox-guest-utils</em></p>
<p>Le premier nécessite le paquet linux-headers (ou linux-lts-headers), le deuxième propose les modules noyaux déjà précompilés. <strong>On choisit donc la deuxième option.</strong></p>
<p><strong>Note 3 :</strong> si vous avez décidé dinstaller le noyau lts, il faut installer les paquets linux-lts-headers et virtualbox-guest-dkms. Il ny a plus de modules précompilés pour le noyau linux-lts</p>
<p>La prise en charge des modules noyau se fait avec la commande systemctl suivante :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl enable vboxservice
</code></pre></div></div>
<p><strong>Note :</strong> si vous installez un jour VirtualBox sur une machine réelle je vous renvoie à cette page du wiki francophone : <a href="https://wiki.archlinux.fr/VirtualBox">https://wiki.archlinux.fr/VirtualBox</a></p>
<p>On va rajouter quelques outils, histoire de ne pas voir un environnement vide au premier démarrage.</p>
<p>On commence par tout ce qui est graphique : gimp, cups (gestion de limprimante) et hplip (si vous avez une imprimante scanner Hewlett Packard). Le paquet python-pyqt5 est indispensable pour linterface graphique de HPLIP :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman -S cups gimp gimp-help-fr hplip python-pyqt5
</code></pre></div></div>
<p>La série des paquets foomatic permet davoir le maximum de pilotes pour limprimante. Pour être tranquille avec son imprimante :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman -S foomatic-{db,db-ppds,db-gutenprint-ppds,db-nonfree,db-nonfree-ppds} gutenprint
</code></pre></div></div>
<p>Depuis la fin juillet 2014, il y a deux versions qui sont supportés par Archlinux pour LibreOffice, en conformité avec ce que propose la Document Foundation. Pour la version <strong>stable</strong> et les utilisateurs <strong>prudents</strong>, on utilise la ligne de commande :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman -S libreoffice-still-fr
</code></pre></div></div>
<p>Pour les utilisateurs plus <strong>aventureux</strong>, qui veulent la version récente :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman -S libreoffice-fresh-fr
</code></pre></div></div>
<p>On rajoute ensuite Mozilla Firefox en français :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman -S firefox-i18n-fr
</code></pre></div></div>
<p>Vous préférez Chromium ?</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman -S chromium
</code></pre></div></div>
<p>On crée un utilisateur avec la commande suivante, qui sera indispensable pour appliquer un des addenda si vous ne voulez pas utiliser Gnome.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>useradd -m -g wheel -c 'Nom complet de lutilisateur' -s /bin/bash nom-de-lutilisateur **sur une seule ligne !**
passwd nom-de-lutilisateur
</code></pre></div></div>
<p>Avant de finir, on va configurer sudo en utilisant visudo. En effet, il nous suffit de modifier une ligne pour que lon puisse accéder en tant quutilisateur classique aux droits complets sur la machine de manière temporaire.</p>
<p>Il faut aller, en utilisant la flèche du bas jusquà la ligne :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#Uncomment to allow members of group wheel to execute any command
</code></pre></div></div>
<p>Et enlever le # sur la ligne qui suit. La séquence de touches « Échap : w et q » permet de converser la modification.</p>
<p><strong>À partir dici, cest la section dédiée à Gnome qui commence :</strong></p>
<p>On passe enfin au morceau de choix : linstallation de Gnome, les extensions étant indispensables pour avoir le mode « Gnome Classique ». Le paquet telepathy permet dajouter le maximum de support pour les comptes utilisateurs en ligne.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman -S gnome gnome-extra system-config-printer telepathy shotwell rhythmbox
</code></pre></div></div>
<p>Si vous voulez utiliser loutils Gnome Logiciels, même si ce nest pas des plus fonctionnels sous Archlinux :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman -S gnome-software
</code></pre></div></div>
<p>Linstallation de Gnome est maintenant terminée.</p>
<p><strong>Fin de la section uniquement consacrée à Gnome, ici, il y a des points communs à tous les environnements proposés.</strong></p>
<p>Pour être certain davoir le bon clavier au démarrage de GDM ou dun autre gestionnaire de connexion comme sddm, lightdm ou lxdm, voici une petite commande à lancer (en modifiant le clavier selon les besoins) :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo localectl set-x11-keymap fr
</code></pre></div></div>
<p>Les valeurs étant à adapter en fonction de la locale et du clavier, bien entendu.</p>
<p><strong>Note 4 :</strong> Si vous avez besoin de gérer des périphériques utilisant MTP (tablettes sous android par exemple), il vous faut rajouter les deux paquets gvfs-mtp et mtpfs.</p>
<p>Étant donné que systemd est utilisé, voici la liste des services à activer (avec une explication rapide), <strong>qui sera la même pour chacun des environnements</strong> proposés dans les « addenda » :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl enable syslog-ng → *gestion des fichiers denregistrement dactivité*
systemctl enable cronie → *pour les tâches récurrentes*
systemctl enable avahi-daemon → *dépendance de Cups*
systemctl enable avahi-dnsconfd → *autre dépendance de Cups*
systemctl enable org.cups.cupsd → *cups pour les imprimantes*
systemctl enable bluetooth → *uniquement si on a du matériel bluetooth*
systemctl enable ntpd → *pour synchroniser lheure en réseau.*
</code></pre></div></div>
<p><strong>Note 5</strong> : dans un premier temps, il ne faut pas activer le gestionnaire de connexion de lenvironnement choisi. On fait uniquement un systemctl start suivi du nom du gestionnaire en question.</p>
<p>Comme je présente Gnome dans la section principale, cest GDM. Sinon, il faut se référer à laddenda correspondant.</p>
<p>Sinon, il suffit de se référer à laddenda correspondant à lenvironnement de votre choix.</p>
<p>Au démarrage suivant, GDM nous accueille, et nous pouvons nous connecter.</p>
<p><img src="file://pictures/010.png" alt="Illustration 10: GDM 3.24.2 avec les sessions Wayland et Gnome sur Xorg" /></p>
<p><em>Illustration 10: GDM 3.24.2 avec les sessions Wayland et Gnome sur Xorg</em></p>
<h2 id="iii-finalisons-linstallation-de-gnome">III) Finalisons linstallation de Gnome.</h2>
<p><strong>Note :</strong> à partir de maintenant, nous sommes connectés en tant quutilisateur classique.</p>
<p>Quelques outils à rajouter : xsane (pour le scanner), mais aussi unoconv (pour laperçu des fichiers dans Gnome Documents). On pourrait rajouter Adobe Flash, mais pourquoi rajouter cette usine à faille de sécurité ?</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yaourt -S xsane unoconv
</code></pre></div></div>
<p>Il faut penser à vérifier que le clavier est correctement configuré. Ce qui se fait dans menu système unifié, options de configuration.</p>
<p><img src="file://pictures/011.png" alt="Illustration 11: Gnome 3.24.2 en vue activités" /></p>
<p><em>Illustration 11: Gnome 3.24.2 en vue activités</em></p>
<p>On va personnaliser le bureau Gnome en lui ajoutant la date complète et les boutons pour minimiser et maximiser les fenêtres avec Gnome Tweak Tool.</p>
<p><img src="file://pictures/012.png" alt="Illustration 12: Gnome Tweak Tool en action." /></p>
<p><em>Illustration 12: Gnome Tweak Tool en action.</em></p>
<p>Pour finir des captures décran du mode « Gnome Shell » et « Gnome Classique ».</p>
<p><img src="file://pictures/013.png" alt="Illustration 13: Gnome Shell 3.24.2 et « LibreOffice-fresh »" /></p>
<p><em>Illustration 13: Gnome Shell 3.24.2 et « LibreOffice-fresh »</em></p>
<p><img src="file://pictures/014.png" alt="Illustration 14: Gnome classique 3.24.2 en action" /></p>
<p><em>Illustration 14: Gnome classique 3.24.2 en action</em></p>
<p>Voila, le guide est maintenant fini. Cependant, je nai pas abordé linstallation dun pare-feu. Cest quelque chose de plus technique.</p>
<p>Jai surtout voulu faire un <strong>guide rapide</strong>, histoire de montrer quen une petite heure on pouvait avoir un environnement installé et assez complet pour le fignoler par la suite.</p>
<p>Bonne découverte !</p>
<h2 id="iv-addendum-1--installer-plasma-510x">IV) Addendum 1 : installer Plasma 5.10.x</h2>
<p><strong>Note :</strong> commandes à entrer en tant quutilisateur classique. Si vous navez pas yaourt, sudo pacman -S sera à utiliser. Kde-l10n-fr étant à remplacer par votre locale. Dans les précédentes versions, il y avait k3b, mais il a été intégré dans les kde-applications à partir de la version 17.04.</p>
<p>Linstallation se déroule ainsi :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yaourt -S plasma kde-applications kde-l10n-fr amarok digikam breeze-kde4
</code></pre></div></div>
<p>Le paquet breeze-kde4 permet de donner un thème « KDE 5 » aux applications non encore adaptées pour le nouvel environnement.</p>
<p>Pour avoir le bon agencement clavier dès la saisie du premier caractère du mot de passe, il faut entrer la commande suivant avant de lancer pour la première fois sddm :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo localectl set-x11-keymap fr
</code></pre></div></div>
<p>Bien entendu, la valeur à utiliser après set-x11-keymap doit être identique à celle saisie plus haut quand on a configuré la base dArchlinux. Sans oublier le correctif indiqué plus haut dans la section Gnome concernant le clavier français sous Xorg.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl start sddm
</code></pre></div></div>
<p>Si tout se passe bien, on peut utiliser :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl enable sddm
</code></pre></div></div>
<p><img src="file://pictures/015.png" alt="Illustration 15: Plasma 5.10.x (vue de dossiers) avec les KDE Frameworks 5.34.0" /></p>
<p><em>Illustration 15: Plasma 5.10.x (vue de dossiers) avec les KDE Frameworks 5.34.0</em></p>
<h2 id="v-addendum-2--installer-xfce">V) Addendum 2 : installer Xfce</h2>
<p><strong>Note :</strong> commandes à entrer en tant quutilisateur classique. Si vous navez pas yaourt, sudo pacman -S sera à utiliser.</p>
<p><strong>Note 2 :</strong> si vous avez besoin de gérer des périphériques utilisant MTP (tablettes sous android par exemple), il vous faut rajouter les deux paquets gvfs-mtp et mtpfs.</p>
<p><strong>Note 3 :</strong> courant janvier 2017, gstreamer-0.10 a été déprécié, après 4 ans sans la moindre mise à jour par les développeurs, et par conséquent, le greffon audio de Xfce est désormais celui de Pulseaudio, doù le rajout de pavucontrol dans la liste des paquets.</p>
<p><strong>Note 4 :</strong> VLC a été remplacé par SMPlayer pour des raisons pratiques. VLC reviendra quand il sortira en version 3.0 officielle et finale.</p>
<p>Pour installer Xfce, il faut entrer :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yaourt -S xfce4 xfce4-goodies gvfs smplayer quodlibet python2-pyinotify lightdm-gtk-greeter midori xarchiver claws-mail galculator evince ffmpegthumbnailer xscreensaver pavucontrol pulseaudio pulseaudio-alsa libcanberra-{pulse,gstreamer} system-config-printer **→ (pour installer le support des imprimantes)**
</code></pre></div></div>
<p>SMPlayer et Quodlibet ? Pour la vidéo et laudio. Midori ? Pour la navigation internet. Pour les périphériques amovibles, gvfs est obligatoire. Claws-mail ou Mozilla Thunderbird (avec le paquet thunderbird-i18n-fr) pour le courrier. Lightdm étant pris, car plus rapide à installer. Le paquet python2-pyinotify est nécessaire pour activer le greffon de mise à jour automatique de la musicothèque sous Quodlibet.</p>
<p>Evince ? Pour les fichiers en pdf. On peut aussi remplacer xarchiver par fileroller. Quant à ffmpegthumbnailer, cest utile si vous désirez avoir un aperçu des vidéos stockées sur votre ordinateur. Enfin, xscreensaver sert au verrouillage de lécran.</p>
<p>Si vous utilisez NetworkManager, vous pouvez rajouter lapplet pour gérer et surveiller votre réseau avec le paquet « network-manager-applet ». Si vous voulez personnaliser votre lightdm :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yaourt -S lightdm-gtk-greeter-settings
</code></pre></div></div>
<p>Pour avoir le bon agencement clavier dès la saisie du premier caractère du mot de passe, il faut entrer la commande suivant avant de lancer pour la première fois lightdm :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo localectl set-x11-keymap fr
</code></pre></div></div>
<p>Pour lancer Xfce, il faut entrer dans un premier temps :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl start lightdm
</code></pre></div></div>
<p>Et si tout se passe bien, on peut utiliser :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl enable lightdm
</code></pre></div></div>
<p><strong>Note 5 :</strong> pour avoir des plus jolies icônes, on peut installer le paquet AUR elementary-xfce-icons ou encore les mint-x-icons. mais après, cest à vous de voir !</p>
<p><img src="file://pictures/016.png" alt="Illustration 16: Xfce 4.12.0 en action." /></p>
<p><em>Illustration 16: Xfce 4.12.0 en action.</em></p>
<h2 id="vi-addendum-3--installer-mate-desktop">VI) Addendum 3 : installer Mate-Desktop</h2>
<p><strong>Note :</strong> commandes à entrer en tant quutilisateur classique. Si vous navez pas yaourt, sudo pacman -S sera à utiliser.</p>
<p><strong>Note 2 :</strong> Mate 1.18 étant uniquement en gtk3, cela simplifie linstallation.</p>
<p><strong>Note 3 :</strong> Si vous avez besoin de gérer des périphériques utilisant MTP (tablettes sous android par exemple), il vous faut rajouter les deux paquets gvfs-mtp et mtpfs.</p>
<p>Linstallation ressemble à celle de Xfce, donc pour les explications des paquets, cf laddenda consacré à Xfce. Idem pour lutilisation de NetworkManager si vous le voulez. Il ne faut pas oublier de rajouter un outil de gravure, comme Brasero si nécessaire. Pour le navigateur, Mozilla Firefox, Chromium ou encore Midori. Cest selon les goûts !</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yaourt -S mate mate-extra lightdm-gtk-greeter gnome-icon-theme smplayer quodlibet python2-pyinotify accountsservice claws-mail system-config-printer gtk3-print-backends **→** **(pour installer le support des imprimantes)**
</code></pre></div></div>
<p>Si vous voulez personnaliser votre lightdm :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yaourt -S lightdm-gtk-greeter-settings
</code></pre></div></div>
<p>Pour avoir le bon agencement clavier dès la saisie du premier caractère du mot de passe, il faut entrer la commande suivant avant de lancer pour la première fois lightdm :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo localectl set-x11-keymap fr
</code></pre></div></div>
<p>Pour lancer Mate Desktop, il faut entrer dans un premier temps :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl start accounts-daemon
sudo systemctl start lightdm
</code></pre></div></div>
<p>Si tout se passe bien, on peut utiliser :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl enable accounts-daemon
sudo systemctl enable lightdm
</code></pre></div></div>
<p><img src="file://pictures/017.png" alt="Illustration 17: Mate Desktop 1.18.0" /></p>
<p><em>Illustration 17: Mate Desktop 1.18.0</em></p>
</div>
<div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2019-12-25T00:00:00+01:00"><!-- start custom article footer snippet -->
<!-- end custom article footer snippet -->
<!--
<div align="right"><a type="application/rss+xml" href="/feed.xml" title="S'abonner"><i class="fa fa-rss fa-2x"></i></a>
&emsp;</div>
-->
</footer>
<div class="article__section-navigator clearfix"><div class="previous"><span>PRÉCÉDENT</span><a href="/2019/12/25/Archlinux-32.html">Archlinux-32</a></div><div class="next"><span>SUIVANT</span><a href="/2019/12/25/Asus-R505C.html">Asus-R505C</a></div></div></div>
</div>
<script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
$(function() {
var $this ,$scroll;
var $articleContent = $('.js-article-content');
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
var scroll = hasSidebar ? '.js-page-main' : 'html, body';
$scroll = $(scroll);
$articleContent.find('.highlight').each(function() {
$this = $(this);
$this.attr('data-lang', $this.find('code').attr('data-lang'));
});
$articleContent.find('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]').each(function() {
$this = $(this);
$this.append($('<a class="anchor d-print-none" aria-hidden="true"></a>').html('<i class="fas fa-anchor"></i>'));
});
$articleContent.on('click', '.anchor', function() {
$scroll.scrollToAnchor('#' + $(this).parent().attr('id'), 400);
});
});
});
})();
</script>
</div><section class="page__comments d-print-none"></section></article><!-- start custom main bottom snippet -->
<!-- end custom main bottom snippet -->
</div>
</div></div></div></div>
</div><script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
var $body = $('body'), $window = $(window);
var $pageRoot = $('.js-page-root'), $pageMain = $('.js-page-main');
var activeCount = 0;
function modal(options) {
var $root = this, visible, onChange, hideWhenWindowScroll = false;
var scrollTop;
function setOptions(options) {
var _options = options || {};
visible = _options.initialVisible === undefined ? false : show;
onChange = _options.onChange;
hideWhenWindowScroll = _options.hideWhenWindowScroll;
}
function init() {
setState(visible);
}
function setState(isShow) {
if (isShow === visible) {
return;
}
visible = isShow;
if (visible) {
activeCount++;
scrollTop = $(window).scrollTop() || $pageMain.scrollTop();
$root.addClass('modal--show');
$pageMain.scrollTop(scrollTop);
activeCount === 1 && ($pageRoot.addClass('show-modal'), $body.addClass('of-hidden'));
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.on('scroll', hide);
$window.on('keyup', handleKeyup);
} else {
activeCount > 0 && activeCount--;
$root.removeClass('modal--show');
$window.scrollTop(scrollTop);
activeCount === 0 && ($pageRoot.removeClass('show-modal'), $body.removeClass('of-hidden'));
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.off('scroll', hide);
$window.off('keyup', handleKeyup);
}
onChange && onChange(visible);
}
function show() {
setState(true);
}
function hide() {
setState(false);
}
function handleKeyup(e) {
// Char Code: 27 ESC
if (e.which === 27) {
hide();
}
}
setOptions(options);
init();
return {
show: show,
hide: hide,
$el: $root
};
}
$.fn.modal = modal;
});
})();
</script><div class="modal modal--overflow page__search-modal d-print-none js-page-search-modal"><script>
(function () {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
// search panel
var search = (window.search || (window.search = {}));
var useDefaultSearchBox = window.useDefaultSearchBox === undefined ?
true : window.useDefaultSearchBox ;
var $searchModal = $('.js-page-search-modal');
var $searchToggle = $('.js-search-toggle');
var searchModal = $searchModal.modal({ onChange: handleModalChange, hideWhenWindowScroll: true });
var modalVisible = false;
search.searchModal = searchModal;
var $searchBox = null;
var $searchInput = null;
var $searchClear = null;
function getModalVisible() {
return modalVisible;
}
search.getModalVisible = getModalVisible;
function handleModalChange(visible) {
modalVisible = visible;
if (visible) {
search.onShow && search.onShow();
useDefaultSearchBox && $searchInput[0] && $searchInput[0].focus();
} else {
search.onShow && search.onHide();
useDefaultSearchBox && $searchInput[0] && $searchInput[0].blur();
setTimeout(function() {
useDefaultSearchBox && ($searchInput.val(''), $searchBox.removeClass('not-empty'));
search.clear && search.clear();
window.pageAsideAffix && window.pageAsideAffix.refresh();
}, 400);
}
}
$searchToggle.on('click', function() {
modalVisible ? searchModal.hide() : searchModal.show();
});
// Char Code: 83 S, 191 /
$(window).on('keyup', function(e) {
if (!modalVisible && !window.isFormElement(e.target || e.srcElement) && (e.which === 83 || e.which === 191)) {
modalVisible || searchModal.show();
}
});
if (useDefaultSearchBox) {
$searchBox = $('.js-search-box');
$searchInput = $searchBox.children('input');
$searchClear = $searchBox.children('.js-icon-clear');
search.getSearchInput = function() {
return $searchInput.get(0);
};
search.getVal = function() {
return $searchInput.val();
};
search.setVal = function(val) {
$searchInput.val(val);
};
$searchInput.on('focus', function() {
$(this).addClass('focus');
});
$searchInput.on('blur', function() {
$(this).removeClass('focus');
});
$searchInput.on('input', window.throttle(function() {
var val = $(this).val();
if (val === '' || typeof val !== 'string') {
search.clear && search.clear();
} else {
$searchBox.addClass('not-empty');
search.onInputNotEmpty && search.onInputNotEmpty(val);
}
}, 400));
$searchClear.on('click', function() {
$searchInput.val(''); $searchBox.removeClass('not-empty');
search.clear && search.clear();
});
}
});
})();
</script><div class="search search--dark">
<div class="main">
<div class="search__header">Recherche</div>
<div class="search-bar">
<div class="search-box js-search-box">
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
<input id="search-input" type="text" />
<div class="search-box__icon-clear js-icon-clear">
<a><i class="fas fa-times"></i></a>
</div>
</div>
<button class="button button--theme-dark button--pill search__cancel js-search-toggle">
Annuler</button>
</div>
<div id="results-container" class="search-result js-search-result"></div>
</div>
</div>
<!-- Script pointing to search-script.js -->
<script>/*!
* Simple-Jekyll-Search
* Copyright 2015-2020, Christian Fei
* Licensed under the MIT License.
*/
(function(){
'use strict'
var _$Templater_7 = {
compile: compile,
setOptions: setOptions
}
const options = {}
options.pattern = /\{(.*?)\}/g
options.template = ''
options.middleware = function () {}
function setOptions (_options) {
options.pattern = _options.pattern || options.pattern
options.template = _options.template || options.template
if (typeof _options.middleware === 'function') {
options.middleware = _options.middleware
}
}
function compile (data) {
return options.template.replace(options.pattern, function (match, prop) {
const value = options.middleware(prop, data[prop], options.template)
if (typeof value !== 'undefined') {
return value
}
return data[prop] || match
})
}
'use strict';
function fuzzysearch (needle, haystack) {
var tlen = haystack.length;
var qlen = needle.length;
if (qlen > tlen) {
return false;
}
if (qlen === tlen) {
return needle === haystack;
}
outer: for (var i = 0, j = 0; i < qlen; i++) {
var nch = needle.charCodeAt(i);
while (j < tlen) {
if (haystack.charCodeAt(j++) === nch) {
continue outer;
}
}
return false;
}
return true;
}
var _$fuzzysearch_1 = fuzzysearch;
'use strict'
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
function FuzzySearchStrategy () {
this.matches = function (string, crit) {
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
}
}
'use strict'
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
function LiteralSearchStrategy () {
this.matches = function (str, crit) {
if (!str) return false
str = str.trim().toLowerCase()
crit = crit.trim().toLowerCase()
return crit.split(' ').filter(function (word) {
return str.indexOf(word) >= 0
}).length === crit.split(' ').length
}
}
'use strict'
var _$Repository_4 = {
put: put,
clear: clear,
search: search,
setOptions: __setOptions_4
}
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
function NoSort () {
return 0
}
const data = []
let opt = {}
opt.fuzzy = false
opt.limit = 10
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = NoSort
opt.exclude = []
function put (data) {
if (isObject(data)) {
return addObject(data)
}
if (isArray(data)) {
return addArray(data)
}
return undefined
}
function clear () {
data.length = 0
return data
}
function isObject (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
}
function isArray (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
}
function addObject (_data) {
data.push(_data)
return data
}
function addArray (_data) {
const added = []
clear()
for (let i = 0, len = _data.length; i < len; i++) {
if (isObject(_data[i])) {
added.push(addObject(_data[i]))
}
}
return added
}
function search (crit) {
if (!crit) {
return []
}
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
}
function __setOptions_4 (_opt) {
opt = _opt || {}
opt.fuzzy = _opt.fuzzy || false
opt.limit = _opt.limit || 10
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = _opt.sort || NoSort
opt.exclude = _opt.exclude || []
}
function findMatches (data, crit, strategy, opt) {
const matches = []
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
const match = findMatchesInObject(data[i], crit, strategy, opt)
if (match) {
matches.push(match)
}
}
return matches
}
function findMatchesInObject (obj, crit, strategy, opt) {
for (const key in obj) {
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
return obj
}
}
}
function isExcluded (term, excludedTerms) {
for (let i = 0, len = excludedTerms.length; i < len; i++) {
const excludedTerm = excludedTerms[i]
if (new RegExp(excludedTerm).test(term)) {
return true
}
}
return false
}
/* globals ActiveXObject:false */
'use strict'
var _$JSONLoader_2 = {
load: load
}
function load (location, callback) {
const xhr = getXHR()
xhr.open('GET', location, true)
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
xhr.send()
}
function createStateChangeListener (xhr, callback) {
return function () {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
callback(null, JSON.parse(xhr.responseText))
} catch (err) {
callback(err, null)
}
}
}
}
function getXHR () {
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
}
'use strict'
var _$OptionsValidator_3 = function OptionsValidator (params) {
if (!validateParams(params)) {
throw new Error('-- OptionsValidator: required options missing')
}
if (!(this instanceof OptionsValidator)) {
return new OptionsValidator(params)
}
const requiredOptions = params.required
this.getRequiredOptions = function () {
return requiredOptions
}
this.validate = function (parameters) {
const errors = []
requiredOptions.forEach(function (requiredOptionName) {
if (typeof parameters[requiredOptionName] === 'undefined') {
errors.push(requiredOptionName)
}
})
return errors
}
function validateParams (params) {
if (!params) {
return false
}
return typeof params.required !== 'undefined' && params.required instanceof Array
}
}
'use strict'
var _$utils_9 = {
merge: merge,
isJSON: isJSON
}
function merge (defaultParams, mergeParams) {
const mergedOptions = {}
for (const option in defaultParams) {
mergedOptions[option] = defaultParams[option]
if (typeof mergeParams[option] !== 'undefined') {
mergedOptions[option] = mergeParams[option]
}
}
return mergedOptions
}
function isJSON (json) {
try {
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
return true
}
return false
} catch (err) {
return false
}
}
var _$src_8 = {};
(function (window) {
'use strict'
let options = {
searchInput: null,
resultsContainer: null,
json: [],
success: Function.prototype,
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
templateMiddleware: Function.prototype,
sortMiddleware: function () {
return 0
},
noResultsText: 'No results found',
limit: 10,
fuzzy: false,
debounceTime: null,
exclude: []
}
let debounceTimerHandle
const debounce = function (func, delayMillis) {
if (delayMillis) {
clearTimeout(debounceTimerHandle)
debounceTimerHandle = setTimeout(func, delayMillis)
} else {
func.call()
}
}
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
/* removed: const _$Templater_7 = require('./Templater') */;
/* removed: const _$Repository_4 = require('./Repository') */;
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
const optionsValidator = _$OptionsValidator_3({
required: requiredOptions
})
/* removed: const _$utils_9 = require('./utils') */;
window.SimpleJekyllSearch = function (_options) {
const errors = optionsValidator.validate(_options)
if (errors.length > 0) {
throwError('You must specify the following required options: ' + requiredOptions)
}
options = _$utils_9.merge(options, _options)
_$Templater_7.setOptions({
template: options.searchResultTemplate,
middleware: options.templateMiddleware
})
_$Repository_4.setOptions({
fuzzy: options.fuzzy,
limit: options.limit,
sort: options.sortMiddleware,
exclude: options.exclude
})
if (_$utils_9.isJSON(options.json)) {
initWithJSON(options.json)
} else {
initWithURL(options.json)
}
const rv = {
search: search
}
typeof options.success === 'function' && options.success.call(rv)
return rv
}
function initWithJSON (json) {
_$Repository_4.put(json)
registerInput()
}
function initWithURL (url) {
_$JSONLoader_2.load(url, function (err, json) {
if (err) {
throwError('failed to get JSON (' + url + ')')
}
initWithJSON(json)
})
}
function emptyResultsContainer () {
options.resultsContainer.innerHTML = ''
}
function appendToResultsContainer (text) {
options.resultsContainer.innerHTML += text
}
function registerInput () {
options.searchInput.addEventListener('input', function (e) {
if (isWhitelistedKey(e.which)) {
emptyResultsContainer()
debounce(function () { search(e.target.value) }, options.debounceTime)
}
})
}
function search (query) {
if (isValidQuery(query)) {
emptyResultsContainer()
render(_$Repository_4.search(query), query)
}
}
function render (results, query) {
const len = results.length
if (len === 0) {
return appendToResultsContainer(options.noResultsText)
}
for (let i = 0; i < len; i++) {
results[i].query = query
appendToResultsContainer(_$Templater_7.compile(results[i]))
}
}
function isValidQuery (query) {
return query && query.length > 0
}
function isWhitelistedKey (key) {
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
}
function throwError (message) {
throw new Error('SimpleJekyllSearch --- ' + message)
}
})(window)
}());
</script>
<!-- Configuration -->
<script>
SimpleJekyllSearch({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
noResultsText: '<p>Aucun résultat!</p>',
json: '/search.json',
searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{title}</a>&nbsp;(Création {create})</li>'
})
</script>
</div></div>
<script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function scrollToAnchor(anchor, duration, callback) {
var $root = this;
$root.animate({ scrollTop: $(anchor).position().top }, duration, function() {
window.history.replaceState(null, '', window.location.href.split('#')[0] + anchor);
callback && callback();
});
}
$.fn.scrollToAnchor = scrollToAnchor;
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function affix(options) {
var $root = this, $window = $(window), $scrollTarget, $scroll,
offsetBottom = 0, scrollTarget = window, scroll = window.document, disabled = false, isOverallScroller = true,
rootTop, rootLeft, rootHeight, scrollBottom, rootBottomTop,
hasInit = false, curState;
function setOptions(options) {
var _options = options || {};
_options.offsetBottom && (offsetBottom = _options.offsetBottom);
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
_options.scroll && (scroll = _options.scroll);
_options.disabled !== undefined && (disabled = _options.disabled);
$scrollTarget = $(scrollTarget);
isOverallScroller = window.isOverallScroller($scrollTarget[0]);
$scroll = $(scroll);
}
function preCalc() {
top();
rootHeight = $root.outerHeight();
rootTop = $root.offset().top + (isOverallScroller ? 0 : $scrollTarget.scrollTop());
rootLeft = $root.offset().left;
}
function calc(needPreCalc) {
needPreCalc && preCalc();
scrollBottom = $scroll.outerHeight() - offsetBottom - rootHeight;
rootBottomTop = scrollBottom - rootTop;
}
function top() {
if (curState !== 'top') {
$root.removeClass('fixed').css({
left: 0,
top: 0
});
curState = 'top';
}
}
function fixed() {
if (curState !== 'fixed') {
$root.addClass('fixed').css({
left: rootLeft + 'px',
top: 0
});
curState = 'fixed';
}
}
function bottom() {
if (curState !== 'bottom') {
$root.removeClass('fixed').css({
left: 0,
top: rootBottomTop + 'px'
});
curState = 'bottom';
}
}
function setState() {
var scrollTop = $scrollTarget.scrollTop();
if (scrollTop >= rootTop && scrollTop <= scrollBottom) {
fixed();
} else if (scrollTop < rootTop) {
top();
} else {
bottom();
}
}
function init() {
if(!hasInit) {
var interval, timeout;
calc(true); setState();
// run calc every 100 millisecond
interval = setInterval(function() {
calc();
}, 100);
timeout = setTimeout(function() {
clearInterval(interval);
}, 45000);
window.pageLoad.then(function() {
setTimeout(function() {
clearInterval(interval);
clearTimeout(timeout);
}, 3000);
});
$scrollTarget.on('scroll', function() {
disabled || setState();
});
$window.on('resize', function() {
disabled || (calc(true), setState());
});
hasInit = true;
}
}
setOptions(options);
if (!disabled) {
init();
}
$window.on('resize', window.throttle(function() {
init();
}, 200));
return {
setOptions: setOptions,
refresh: function() {
calc(true, { animation: false }); setState();
}
};
}
$.fn.affix = affix;
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function toc(options) {
var $root = this, $window = $(window), $scrollTarget, $scroller, $tocUl = $('<ul class="toc toc--ellipsis"></ul>'), $tocLi, $headings, $activeLast, $activeCur,
selectors = 'h1,h2,h3', container = 'body', scrollTarget = window, scroller = 'html, body', disabled = false,
headingsPos, scrolling = false, hasRendered = false, hasInit = false;
function setOptions(options) {
var _options = options || {};
_options.selectors && (selectors = _options.selectors);
_options.container && (container = _options.container);
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
_options.scroller && (scroller = _options.scroller);
_options.disabled !== undefined && (disabled = _options.disabled);
$headings = $(container).find(selectors).filter('[id]');
$scrollTarget = $(scrollTarget);
$scroller = $(scroller);
}
function calc() {
headingsPos = [];
$headings.each(function() {
headingsPos.push(Math.floor($(this).position().top));
});
}
function setState(element, disabled) {
var scrollTop = $scrollTarget.scrollTop(), i;
if (disabled || !headingsPos || headingsPos.length < 1) { return; }
if (element) {
$activeCur = element;
} else {
for (i = 0; i < headingsPos.length; i++) {
if (scrollTop >= headingsPos[i]) {
$activeCur = $tocLi.eq(i);
} else {
$activeCur || ($activeCur = $tocLi.eq(i));
break;
}
}
}
$activeLast && $activeLast.removeClass('active');
($activeLast = $activeCur).addClass('active');
}
function render() {
if(!hasRendered) {
$root.append($tocUl);
$headings.each(function() {
var $this = $(this);
$tocUl.append($('<li></li>').addClass('toc-' + $this.prop('tagName').toLowerCase())
.append($('<a></a>').text($this.text()).attr('href', '#' + $this.prop('id'))));
});
$tocLi = $tocUl.children('li');
$tocUl.on('click', 'a', function(e) {
e.preventDefault();
var $this = $(this);
scrolling = true;
setState($this.parent());
$scroller.scrollToAnchor($this.attr('href'), 400, function() {
scrolling = false;
});
});
}
hasRendered = true;
}
function init() {
var interval, timeout;
if(!hasInit) {
render(); calc(); setState(null, scrolling);
// run calc every 100 millisecond
interval = setInterval(function() {
calc();
}, 100);
timeout = setTimeout(function() {
clearInterval(interval);
}, 45000);
window.pageLoad.then(function() {
setTimeout(function() {
clearInterval(interval);
clearTimeout(timeout);
}, 3000);
});
$scrollTarget.on('scroll', function() {
disabled || setState(null, scrolling);
});
$window.on('resize', window.throttle(function() {
if (!disabled) {
render(); calc(); setState(null, scrolling);
}
}, 100));
}
hasInit = true;
}
setOptions(options);
if (!disabled) {
init();
}
$window.on('resize', window.throttle(function() {
init();
}, 200));
return {
setOptions: setOptions
};
}
$.fn.toc = toc;
});
})();
/*(function () {
})();*/
</script><script>
/* toc must before affix, since affix need to konw toc' height. */(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
var TOC_SELECTOR = window.TEXT_VARIABLES.site.toc.selectors;
window.Lazyload.js(SOURCES.jquery, function() {
var $window = $(window);
var $articleContent = $('.js-article-content');
var $tocRoot = $('.js-toc-root'), $col2 = $('.js-col-aside');
var toc;
var tocDisabled = false;
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
var hasToc = $articleContent.find(TOC_SELECTOR).length > 0;
function disabled() {
return $col2.css('display') === 'none' || !hasToc;
}
tocDisabled = disabled();
toc = $tocRoot.toc({
selectors: TOC_SELECTOR,
container: $articleContent,
scrollTarget: hasSidebar ? '.js-page-main' : null,
scroller: hasSidebar ? '.js-page-main' : null,
disabled: tocDisabled
});
$window.on('resize', window.throttle(function() {
tocDisabled = disabled();
toc && toc.setOptions({
disabled: tocDisabled
});
}, 100));
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
var $window = $(window), $pageFooter = $('.js-page-footer');
var $pageAside = $('.js-page-aside');
var affix;
var tocDisabled = false;
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
affix = $pageAside.affix({
offsetBottom: $pageFooter.outerHeight(),
scrollTarget: hasSidebar ? '.js-page-main' : null,
scroller: hasSidebar ? '.js-page-main' : null,
scroll: hasSidebar ? $('.js-page-main').children() : null,
disabled: tocDisabled
});
$window.on('resize', window.throttle(function() {
affix && affix.setOptions({
disabled: tocDisabled
});
}, 100));
window.pageAsideAffix = affix;
});
})();
</script><!---->
</div>
<script>(function () {
var $root = document.getElementsByClassName('root')[0];
if (window.hasEvent('touchstart')) {
$root.dataset.isTouch = true;
document.addEventListener('touchstart', function(){}, false);
}
})();
</script>
</body>
</html>